package core;



import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;

import java.time.Instant;

public class Totp {
    public static String generateTOTP(String key, int period) {
        long timestamp = Instant.now().getEpochSecond();
        int digits = 6;
        String algorithm = "HmacSHA1"; // 或使用"HmacSHA256" 或 "HmacSHA512"

        long timeStep = timestamp / period;

        try {
            byte[] keyBytes = base32ToBytes(key);
            byte[] msg = new byte[8];

            for (int i = 7; i >= 0; i--) {
                msg[i] = (byte) (timeStep & 0xFF);
                timeStep >>= 8;
            }

            SecretKeySpec keySpec = new SecretKeySpec(keyBytes, algorithm);
            Mac mac = Mac.getInstance(algorithm);
            mac.init(keySpec);
            byte[] hash = mac.doFinal(msg);

            int offset = hash[hash.length - 1] & 0x0F;
            int binary = ((hash[offset] & 0x7F) << 24) |
                    ((hash[offset + 1] & 0xFF) << 16) |
                    ((hash[offset + 2] & 0xFF) << 8) |
                    (hash[offset + 3] & 0xFF);

            int otp = binary % (int) Math.pow(10, digits);
            return String.format("%0" + digits + "d", otp);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    public static byte[] base32ToBytes(String base32) {
        String base32chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
        byte[] bytes = new byte[base32.length() * 5 / 8];
        int buffer = 0;
        int bufferLength = 0;

        for (int i = 0; i < base32.length(); i++) {
            char c = base32.charAt(i);
            int val = base32chars.indexOf(c);
            buffer = (buffer << 5) | val;
            bufferLength += 5;

            if (bufferLength >= 8) {
                bytes[i * 5 / 8] = (byte) ((buffer >> (bufferLength - 8)) & 0xFF);
                bufferLength -= 8;
            }
        }

        return bytes;
    }

}
